package org.dawfinn.droiditarian.server;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import org.dawfinn.droiditarian.client.admin.LoginService;
import org.dawfinn.droiditarian.server.data.PMF;
import org.dawfinn.droiditarian.server.data.User;

import com.google.appengine.api.datastore.Email;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService {

	private static final String salt = "$2a$10$quFbXTSjQW3JzSlMPwvjPO";
	private final Random sessionIdRandom = new Random();
	
	@SuppressWarnings("unchecked")
	public String login(String username, String password) {
		Email email = new Email(username);
		PersistenceManager persistenceManager = PMF.get().getPersistenceManager();
		String passwordHash = BCrypt.hashpw(password, salt);
		Query q = persistenceManager.newQuery(User.class);
		q.declareImports("import com.google.appengine.api.datastore.Email");
		q.declareParameters("Email emailParam, String passwordHashParam");
		q.setFilter("email == emailParam && passwordHash == passwordHashParam");
		List<User> result = (List<User>) q.execute(email, passwordHash);

		if (result.size() != 1) {
			System.out.println("size = " + result.size());
			throw new NoSuchElementException();
		}

		User user = result.get(0);

		String sid = getNextSessionId();
		Transaction tx = persistenceManager.currentTransaction();
		tx.begin();
		user.setCurrentSid(sid);
		tx.commit();
		return sid;
	}

	@SuppressWarnings("unchecked")
	public boolean verifySid(String sid) {
		PersistenceManager persistenceManager = PMF.get().getPersistenceManager();
		Query q = persistenceManager.newQuery(User.class);
		q.declareParameters("String sid");
		q.setFilter("currentSid == sid");
		List<User> result = (List<User>) q.execute(sid);

		return result.size() >= 1;
	}

	@SuppressWarnings("unchecked")
	public boolean createUser(String username, String password) {
		Email email = new Email(username);

		PersistenceManager persistenceManager = PMF.get().getPersistenceManager();
		Query q = persistenceManager.newQuery(User.class);
		q.declareImports("import com.google.appengine.api.datastore.Email");
		q.declareParameters("Email emailParam");
		q.setFilter("email == emailParam");
		List<User> result = (List<User>) q.execute(email);
		if (result.size() > 1) {
			System.out.println("size = " + result.size());
			return false;
		}

		if (result.size() == 1) {
			System.out.println("size = " + result.size());
			User user = result.get(0);
			Transaction tx = persistenceManager.currentTransaction();
			tx.begin();
			user.setPasswordHash(BCrypt.hashpw(password, salt));
			tx.commit();
		} else {

			User newUser = new User(email, BCrypt.hashpw(password, salt));
			persistenceManager.makePersistent(newUser);

		}
		return true;
	}

	private String getNextSessionId() {
		return "" + sessionIdRandom.nextLong();
	}
}
